package com.example.yx1.demo42;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Optional;

@Configuration
public class A42_1 {

    public static void main(String[] args) throws Exception{
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(A42_1.class);
        DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();

        // 1.根据成员变量的类型注入
        DependencyDescriptor dd1 = new DependencyDescriptor(Bean1.class.getDeclaredField("bean2"),false);
        Object bean1 = beanFactory.doResolveDependency(dd1, "bean1", null, null);
        System.out.println(bean1);

        // 2.根据参数的类型注入
        Method setBean2 = Bean1.class.getMethod("setBean2", Bean2.class);
        DependencyDescriptor dd2 = new DependencyDescriptor(new MethodParameter(setBean2,0),false);
        Object bean2 = beanFactory.doResolveDependency(dd1, "bean2", null, null);
        System.out.println(bean2);

        // 3.结果包装为 Optional <Bean2>
        DependencyDescriptor dd3 = new DependencyDescriptor(Bean1.class.getDeclaredField("bean3"), false);
        if (dd3.getDependencyType() == Optional.class) {
            dd3.increaseNestingLevel();
            Object bean3 = beanFactory.doResolveDependency(dd3, "bean3", null, null);
            Optional<Object> res = Optional.ofNullable(bean3);
            System.out.println(res);
        }

        // 4.结果包装为 ObjectProvider
        DependencyDescriptor dd4 = new DependencyDescriptor(Bean1.class.getDeclaredField("bean4"), false);
        if (dd4.getDependencyType() == ObjectFactory.class) {
            dd4.increaseNestingLevel();
            ObjectFactory objectFactory = new ObjectFactory (){
                @Override
                public Object getObject() throws BeansException {
                    Object bean4 = beanFactory.doResolveDependency(dd4, "bean4", null, null);
                    return bean4;
                }
            };
            System.out.println(objectFactory);
            System.out.println(objectFactory.getObject());
        }

        // 5.对 @Lazy 的处理
        Method setBean21 = Bean1.class.getMethod("setBean2", Bean2.class);
        DependencyDescriptor dd5 = new DependencyDescriptor(new MethodParameter(setBean2,0),false);

        ContextAnnotationAutowireCandidateResolver resolver = new ContextAnnotationAutowireCandidateResolver();
        resolver.setBeanFactory(beanFactory);
        Object bean5 = resolver.getLazyResolutionProxyIfNecessary(dd5, "bean5");
        System.out.println(bean5);
        System.out.println(bean5.getClass());


    }


    static class Bean1 {
        @Autowired
        private Bean2 bean2;

        @Autowired
        public void setBean2(@Lazy Bean2 bean2) {this.bean2 = bean2;}

        @Autowired
        private Optional<Bean2> bean3;

        @Autowired
        private ObjectFactory<Bean2> bean4;
    }

    @Component("bean2")
    static class Bean2 {}
}
